// 引入 G6 主库
import G6 from "@antv/g6/build/g6";
// 引入生成唯一ID的工具函数
import { uniqueId } from '@/utils'
// 定义最小箭头尺寸，防止箭头过小
const MIN_ARROW_SIZE = 3

const customEdge = {
  // 初始化注册自定义边类型
  init() {
    // dashArray 用于虚线动画的不同阶段
    const dashArray = [
      [0, 1],
      [0, 2],
      [1, 2],
      [0, 1, 1, 2],
      [0, 2, 1, 2],
      [1, 2, 1, 2],
      [2, 2, 1, 2],
      [3, 2, 1, 2],
      [4, 2, 1, 2]
    ];
    // lineDash 是虚线的基本样式
    const lineDash = [4,2,1,2];
    // interval 控制动画帧数
    const interval = 9;
    // 注册自定义边 customEdge
    G6.registerEdge('customEdge', {
      /**
       * 绘制主边的路径
       * @param {object} cfg 边的配置项，包含 source/target/start/end/shape 等
       * @param {object} group G6 的分组容器
       * @returns {object} keyShape 主路径 shape
       */
      draw(cfg, group) {
        let sourceNode, targetNode, start, end
        // 兼容 source/target 可能为字符串 id 的情况
        if (typeof (cfg.source) === 'string') {
          cfg.source = cfg.sourceNode
        }
        // 设置默认起点/终点偏移，防止边重叠在节点中心
        if(!cfg.start){
          cfg.start={ x:0, y:17 }
        }
        if(!cfg.end){
          cfg.end={ x:0, y:-17 }
        }
        // 计算起点坐标（节点中心+偏移）
        if (!cfg.source.x) {
          sourceNode = cfg.source.getModel()
          start = { x: sourceNode.x + cfg.start.x, y: sourceNode.y + cfg.start.y }
        } else {
          start = cfg.source
        }
        // 计算终点坐标（节点中心+偏移）
        if (typeof (cfg.target) === 'string') {
          cfg.target = cfg.targetNode
        }
        if (!cfg.target.x) {
          targetNode = cfg.target.getModel()
          end = { x: targetNode.x + cfg.end.x, y: targetNode.y +  cfg.end.y }
        } else {
          end = cfg.target
        }
        // 构造贝塞尔曲线路径，hgap 控制曲线弯曲程度
        let path = []
        let hgap = Math.abs(end.x - start.x)
        path = [
          ['M', start.x, start.y], // 移动到起点
          [
            'C',
            start.x,
            start.y + hgap / (hgap / 50), // 控制点1
            end.x,
            end.y - hgap / (hgap / 50),   // 控制点2
            end.x,
            end.y - 4                     // 终点前一点
          ],
          [
            'L',
            end.x,
            end.y                         // 终点
          ]
        ]
        // 箭头参数计算
        let lineWidth = 1;
        lineWidth = lineWidth > MIN_ARROW_SIZE ? lineWidth : MIN_ARROW_SIZE;
        const width = lineWidth * 10 / 3;
        const halfHeight = lineWidth * 4 / 3;
        const radius = lineWidth * 4;
        // 箭头路径
        const endArrowPath = [
          ['M', -width, halfHeight],
          ['L', 0, 0],
          ['L', -width, -halfHeight],
          ['A', radius, radius, 0, 0, 1, -width, halfHeight],
          ['Z']
        ];
        // 添加主路径 shape
        const keyShape = group.addShape('path', {
          attrs: {
            id: 'edge' + uniqueId(), // 唯一ID
            path: path,              // 路径
            stroke: '#b8c3ce',       // 边颜色
            lineAppendWidth: 10,     // 增加点击区域
            endArrow: {
              path: endArrowPath,    // 箭头路径
            }
          }
        });
        return keyShape
      },
      /**
       * 边绘制后动画（如虚线流动效果）
       * @param {object} cfg 边的配置项
       * @param {object} group G6 的分组容器
       */
      afterDraw(cfg, group) {
        // 判断是否需要动画（如起点和终点都处于某种状态）
        if (cfg.source.getModel().isDoingStart && cfg.target.getModel().isDoingEnd) {
          const shape = group.get('children')[0]; // 获取主 shape
          const length = shape.getTotalLength(); // 获取路径总长
          let totalArray = [];
          // 构造虚线动画数组
          for (var i = 0; i < length; i += interval) {
            totalArray = totalArray.concat(lineDash);
          }
          let index = 0;
          // 启动动画，onFrame 每帧更新 lineDash
          shape.animate({
            onFrame() {
              const cfg = {
                lineDash: dashArray[index].concat(totalArray)
              };
              index = (index + 1) % interval;
              return cfg;
            },
            repeat: true
          }, 3000);
        }
      },
      /**
       * 设置边的状态（如选中、悬浮）
       * @param {string} name 状态名
       * @param {boolean} value 状态值
       * @param {object} item 边的 G6 实例
       */
      setState(name, value, item) {
        const group = item.getContainer();
        const shape = group.get("children")[0]; // 获取主 shape
        // 选中/悬浮样式
        const selectStyles = () => {
          shape.attr("stroke", "#6ab7ff"); // 高亮颜色
        };
        // 未选中样式
        const unSelectStyles = () => {
          shape.attr("stroke", "#b8c3ce"); // 默认颜色
        };
        switch (name) {
          case "selected":
          case "hover":
            if (value) {
              selectStyles()
            } else {
              unSelectStyles()
            }
            break;
        }
      }
    });
    // 注册辅助连线边 link-edge（用于拖拽临时边）
    G6.registerEdge('link-edge', {
      /**
       * 绘制直线边
       * @param {object} cfg 边的配置项
       * @param {object} group G6 的分组容器
       * @returns {object} keyShape 主路径 shape
       */
      draw(cfg, group) {
        let sourceNode, targetNode, start, end
        // 计算起点
        if (!cfg.source.x) {
          sourceNode = cfg.source.getModel()
          start = { x: sourceNode.x + cfg.start.x, y: sourceNode.y + cfg.start.y }
        } else {
          start = cfg.source
        }
        // 计算终点
        if (!cfg.target.x) {
          targetNode = cfg.target.getModel()
          end = { x: targetNode.x + cfg.end.x, y: targetNode.y + cfg.end.y }
        } else {
          end = cfg.target
        }
        // 直线路径
        let path = []
        path = [
          ['M', start.x, start.y], // 起点
          ['L', end.x, end.y]      // 终点
        ]
        // 添加 shape
        const keyShape = group.addShape('path', {
          attrs: {
            id: 'edge' + uniqueId(),
            path: path,
            stroke: '#1890FF',      // 边颜色
            strokeOpacity: 0.9,     // 透明度
            lineDash: [5, 5]        // 虚线样式
          }
        });
        return keyShape
      },
    });
  }
}

export default customEdge
